home *** CD-ROM | disk | FTP | other *** search
/ Visual Cafe 3 / Visual Cafe 3.ISO / Vcafe / Main.bin / URLConnection.java < prev    next >
Text File  |  1998-09-22  |  41KB  |  1,104 lines

  1. /*
  2.  * @(#)URLConnection.java    1.33 98/08/17
  3.  *
  4.  * Copyright 1995-1998 by Sun Microsystems, Inc.,
  5.  * 901 San Antonio Road, Palo Alto, California, 94303, U.S.A.
  6.  * All rights reserved.
  7.  * 
  8.  * This software is the confidential and proprietary information
  9.  * of Sun Microsystems, Inc. ("Confidential Information").  You
  10.  * shall not disclose such Confidential Information and shall use
  11.  * it only in accordance with the terms of the license agreement
  12.  * you entered into with Sun.
  13.  */
  14.  
  15. package java.net;
  16.  
  17. import java.io.IOException;
  18. import java.io.InputStream;
  19. import java.io.OutputStream;
  20. import java.util.Hashtable;
  21. import java.util.Date;
  22. import java.util.StringTokenizer;
  23.  
  24. /**
  25.  * The abstract class <code>URLConnection</code> is the superclass 
  26.  * of all classes that represent a communications link between the 
  27.  * application and a URL. Instances of this class can be used both to 
  28.  * read from and to write to the resource referenced by the URL. In 
  29.  * general, creating a connection to a URL is a multistep process: 
  30.  * <p>
  31.  * <center><table border>
  32.  * <tr><th><code>openConnection()</code></th>
  33.  *     <th><code>connect()</code></th></tr>
  34.  * <tr><td>Manipulate parameters that affect the connection to the remote 
  35.  *         resource.</td>
  36.  *     <td>Interact with the resource; query header fields and
  37.  *         contents.</td></tr>
  38.  * </table>
  39.  * ---------------------------->
  40.  * <br>time</center>
  41.  *
  42.  * <ol>
  43.  * <li>The connection object is created by invoking the
  44.  *     <code>openConnection</code> method on a URL.
  45.  * <li>The setup parameters and general request properties are manipulated.
  46.  * <li>The actual connection to the remote object is made, using the
  47.  *    <code>connect</code> method.
  48.  * <li>The remote object becomes available. The header fields and the contents
  49.  *     of the remote object can be accessed.
  50.  * </ol>
  51.  * <p>
  52.  * The setup parameters are modified using the following methods: 
  53.  * <ul><code>
  54.  *   <li>setAllowUserInteraction
  55.  *   <li>setDoInput
  56.  *   <li>setDoOutput
  57.  *   <li>setIfModifiedSince
  58.  *   <li>setUseCaches
  59.  * </code></ul>
  60.  * <p>
  61.  * and the general request properties are modified using the method:
  62.  * <ul><code>
  63.  *   <li>setRequestProperty
  64.  * </code></ul>
  65.  * <p>
  66.  * Default values for the <code>AllowUserInteraction</code> and 
  67.  * <code>UseCaches</code> parameters can be set using the methods 
  68.  * <code>setDefaultAllowUserInteraction</code> and 
  69.  * <code>setDefaultUseCaches</code>. Default values for general 
  70.  * request properties can be set using the 
  71.  * <code>setDefaultRequestProperty</code> method. 
  72.  * <p>
  73.  * Each of the above <code>set</code> methods has a corresponding 
  74.  * <code>get</code> method to retrieve the value of the parameter or 
  75.  * general request property. The specific parameters and general 
  76.  * request properties that are applicable are protocol specific. 
  77.  * <p>
  78.  * The following methods are used to access the header fields and 
  79.  * the contents after the connection is made to the remote object:
  80.  * <ul><code>
  81.  *   <li>getContent
  82.  *   <li>getHeaderField
  83.  *   <li>getInputStream
  84.  *   <li>getOutputStream
  85.  * </code></ul>
  86.  * <p>
  87.  * Certain header fields are accessed frequently. The methods:
  88.  * <ul><code>
  89.  *   <li>getContentEncoding
  90.  *   <li>getContentLength
  91.  *   <li>getContentType
  92.  *   <li>getDate
  93.  *   <li>getExpiration
  94.  *   <li>getLastModified
  95.  * </code></ul>
  96.  * <p>
  97.  * provide convenient access to these fields. The 
  98.  * <code>getContentType</code> method is used by the 
  99.  * <code>getContent</code> method to determine the type of the remote 
  100.  * object; subclasses may find it convenient to override the 
  101.  * <code>getContentType</code> method.  
  102.  * <p>
  103.  * In the common case, all of the pre-connection parameters and 
  104.  * general request properties can be ignored: the pre-connection 
  105.  * parameters and request properties default to sensible values. For 
  106.  * most clients of this interface, there are only two interesting 
  107.  * methods: <code>getInputStream</code> and <code>getObject</code>, 
  108.  * which are mirrored in the <code>URL</code> class by convenience methods.
  109.  * <p>
  110.  * More information on the request properties and header fields of 
  111.  * an <code>http</code> connection can be found at:
  112.  * <ul><code>
  113.  *   http://www.w3.org/hypertext/WWW/Protocols/HTTP1.0/draft-ietf-http-spec.html
  114.  * </code></ul>
  115.  * <p>
  116.  * Note about <code>fileNameMap</code>: In versions prior to JDK 1.1.6,
  117.  * field <code>fileNameMap</code> of <code>URLConnection</code> was public.
  118.  * In JDK 1.1.6 and later, <code>fileNameMap</code> is private; accessor
  119.  * method <code>getFileNameMap()</code> and mutator method 
  120.  * <code>setFileNameMap(FileNameMap)</code> are added to access it.  
  121.  * This change is also described on the 
  122.  * <a href="http://java.sun.com/products/jdk/1.1/compatibility.html">
  123.  * JDK 1.1.x Compatibility</a> page.
  124.  *
  125.  * @author  James Gosling
  126.  * @version 1.33, 08/17/98
  127.  * @see     java.net.URL#openConnection()
  128.  * @see     java.net.URLConnection#connect()
  129.  * @see     java.net.URLConnection#getContent()
  130.  * @see     java.net.URLConnection#getContentEncoding()
  131.  * @see     java.net.URLConnection#getContentLength()
  132.  * @see     java.net.URLConnection#getContentType()
  133.  * @see     java.net.URLConnection#getDate()
  134.  * @see     java.net.URLConnection#getExpiration()
  135.  * @see     java.net.URLConnection#getHeaderField(int)
  136.  * @see     java.net.URLConnection#getHeaderField(java.lang.String)
  137.  * @see     java.net.URLConnection#getInputStream()
  138.  * @see     java.net.URLConnection#getLastModified()
  139.  * @see     java.net.URLConnection#getOutputStream()
  140.  * @see     java.net.URLConnection#setAllowUserInteraction(boolean)
  141.  * @see     java.net.URLConnection#setDefaultRequestProperty(java.lang.String, java.lang.String)
  142.  * @see     java.net.URLConnection#setDefaultUseCaches(boolean)
  143.  * @see     java.net.URLConnection#setDoInput(boolean)
  144.  * @see     java.net.URLConnection#setDoOutput(boolean)
  145.  * @see     java.net.URLConnection#setIfModifiedSince(long)
  146.  * @see     java.net.URLConnection#setRequestProperty(java.lang.String, java.lang.String)
  147.  * @see     java.net.URLConnection#setUseCaches(boolean)
  148.  * @since   JDK1.0
  149.  */
  150. abstract public class URLConnection {
  151.    /**
  152.      * The URL represents the remote object on the World Wide Web to 
  153.      * which this connection is opened. 
  154.      * <p>
  155.      * The value of this field can be accessed by the 
  156.      * <code>getURL</code> method. 
  157.      * <p>
  158.      * The default value of this variable is the value of the URL 
  159.      * argument in the <code>URLConnection</code> constructor. 
  160.      *
  161.      * @see     java.net.URLConnection#getURL()
  162.      * @see     java.net.URLConnection#url
  163.      * @since   JDK1.0
  164.      */
  165.     protected URL url;
  166.  
  167.    /**
  168.      * This variable is set by the <code>setDoInput</code> method. Its 
  169.      * value is returned by the <code>getDoInput</code> method. 
  170.      * <p>
  171.      * A URL connection can be used for input and/or output. Setting the 
  172.      * <code>doInput</code> flag to <code>true</code> indicates that 
  173.      * the application intends to read data from the URL connection. 
  174.      * <p>
  175.      * The default value of this field is <code>true</code>. 
  176.      *
  177.      * @see     java.net.URLConnection#getDoInput()
  178.      * @see     java.net.URLConnection#setDoInput(boolean)
  179.      * @since   JDK1.0
  180.      */
  181.     protected boolean doInput = true;
  182.  
  183.    /**
  184.      * This variable is set by the <code>setDoOutput</code> method. Its 
  185.      * value is returned by the <code>getDoInput</code> method. 
  186.      * <p>
  187.      * A URL connection can be used for input and/or output. Setting the 
  188.      * <code>doOutput</code> flag to <code>true</code> indicates 
  189.      * that the application intends to write data to the URL connection. 
  190.      * <p>
  191.      * The default value of this field is <code>false</code>. 
  192.      *
  193.      * @see     java.net.URLConnection#getDoOutput()
  194.      * @see     java.net.URLConnection#setDoOutput(boolean)
  195.      * @since   JDK1.0
  196.      */
  197.     protected boolean doOutput = false;
  198.  
  199.     private static boolean defaultAllowUserInteraction = false;
  200.  
  201.    /**
  202.      * If <code>true</code>, this <code>URL</code> is being examined in 
  203.      * a context in which it makes sense to allow user interactions such 
  204.      * as popping up an authentication dialog. If <code>false</code>, 
  205.      * then no user interaction is allowed. 
  206.      * <p>
  207.      * The value of this field can be set by the 
  208.      * <code>setAllowUserInteraction</code> method.
  209.      * Its value is returned by the 
  210.      * <code>getAllowUserInteraction</code> method.
  211.      * Its default value is the value of the argument in the last invocation 
  212.      * of the <code>setDefaultAllowUserInteraction</code> method. 
  213.      *
  214.      * @see     java.net.URLConnection#getAllowUserInteraction()
  215.      * @see     java.net.URLConnection#setAllowUserInteraction(boolean)
  216.      * @see     java.net.URLConnection#setDefaultAllowUserInteraction(boolean)
  217.      * @since   JDK1.0
  218.      */
  219.     protected boolean allowUserInteraction = defaultAllowUserInteraction;
  220.  
  221.     private static boolean defaultUseCaches = true;
  222.  
  223.    /**
  224.      * If <code>true</code>, the protocol is allowed to use caching 
  225.      * whenever it can. If <code>false</code>, the protocol must always 
  226.      * try to get a fresh copy of the object. 
  227.      * <p>
  228.      * This field is set by the <code>setUseCaches</code> method. Its 
  229.      * value is returned by the <code>getUseCaches</code> method.
  230.      * <p>
  231.      * Its default value is the value given in the last invocation of the 
  232.      * <code>setDefaultUseCaches</code> method. 
  233.      *
  234.      * @see     java.net.URLConnection#setUseCaches(boolean)
  235.      * @see     java.net.URLConnection#getUseCaches()
  236.      * @see     java.net.URLConnection#setDefaultUseCaches(boolean)
  237.      * @since   JDK1.0
  238.      */
  239.     protected boolean useCaches = defaultUseCaches;
  240.  
  241.    /**
  242.      * Some protocols support skipping the fetching of the object unless 
  243.      * the object has been modified more recently than a certain time. 
  244.      * <p>
  245.      * A nonzero value gives a time as the number of seconds since 
  246.      * January 1, 1970, GMT. The object is fetched only if it has been 
  247.      * modified more recently than that time. 
  248.      * <p>
  249.      * This variable is set by the <code>setIfModifiedSince</code> 
  250.      * method. Its value is returned by the 
  251.      * <code>getIfModifiedSince</code> method.
  252.      * <p>
  253.      * The default value of this field is <code>0</code>, indicating 
  254.      * that the fetching must always occur. 
  255.      *
  256.      * @see     java.net.URLConnection#getIfModifiedSince()
  257.      * @see     java.net.URLConnection#setIfModifiedSince(long)
  258.      * @since   JDK1.0
  259.      */
  260.     protected long ifModifiedSince = 0;
  261.  
  262.    /**
  263.      * If <code>false</code>, this connection object has not created a 
  264.      * communications link to the specified URL. If <code>true</code>, 
  265.      * the communications link has been established. 
  266.      *
  267.      * @since   JDK1.0
  268.      */
  269.     protected boolean connected = false;
  270.  
  271.    /**
  272.     * @since   JDK1.1
  273.     */
  274.     private static FileNameMap fileNameMap;
  275.  
  276.     /**
  277.      * Returns the FileNameMap.
  278.      *
  279.      * @returns    the FileNameMap
  280.      * @since   JDK1.1
  281.      */
  282.     public static FileNameMap getFileNameMap() {
  283.     return fileNameMap;
  284.     }
  285.  
  286.     /**
  287.      * Sets the FileNameMap.
  288.      *
  289.      * @param map the FileNameMap to be set
  290.      * @since   JDK1.1
  291.      */
  292.     public static void setFileNameMap(FileNameMap map) {
  293.     SecurityManager sm = System.getSecurityManager();
  294.     if (sm != null) sm.checkSetFactory();
  295.     fileNameMap = map;
  296.     }
  297.  
  298.     /**
  299.      * Opens a communications link to the resource referenced by this 
  300.      * URL, if such a connection has not already been established. 
  301.      * <p>
  302.      * If the <code>connect</code> method is called when the connection 
  303.      * has already been opened (indicated by the <code>connected</code> 
  304.      * field having the value <code>true</code>), the call is ignored. 
  305.      * <p>
  306.      * URLConnection objects go through two phases: first they are
  307.      * created, then they are connected.  After being created, and
  308.      * before being connected, various options can be specified
  309.      * (e.g., doInput and UseCaches).  After connecting, it is an
  310.      * error to try to set them.  Operations that depend on being
  311.      * connected, like getContentLength, will implicitly perform the
  312.      * connection, if necessary.
  313.      *
  314.      * @exception  IOException  if an I/O error occurs while opening the
  315.      *               connection.
  316.      * @see        java.net.URLConnection#connected
  317.      * @since      JDK1.0
  318.      */
  319.     abstract public void connect() throws IOException;
  320.  
  321.     /**
  322.      * Constructs a URL connection to the specified URL. A connection to 
  323.      * the object referenced by the URL is not created. 
  324.      *
  325.      * @param   url   the specified URL.
  326.      * @since   JDK1.0
  327.      */
  328.     protected URLConnection(URL url) {
  329.     this.url = url;
  330.     }
  331.  
  332.     /**
  333.      * Returns the value of this <code>URLConnection</code>'s <code>URL</code>
  334.      * field.
  335.      *
  336.      * @return  the value of this <code>URLConnection</code>'s <code>URL</code>
  337.      *          field.
  338.      * @see     java.net.URLConnection#url
  339.      * @since   JDK1.0
  340.      */
  341.     public URL getURL() {
  342.     return url;
  343.     }
  344.  
  345.     /**
  346.      * Returns the value of the <code>content-length</code> header field.
  347.      *
  348.      * @return  the content length of the resource that this connection's URL
  349.      *          references, or <code>-1</code> if the content length is
  350.      *          not known.
  351.      * @since   JDK1.0
  352.      */
  353.     public int getContentLength() {
  354.     return getHeaderFieldInt("content-length", -1);
  355.     }
  356.  
  357.     /**
  358.      * Returns the value of the <code>content-type</code> header field.
  359.      *
  360.      * @return  the content type of the resource that the URL references,
  361.      *          or <code>null</code> if not known.
  362.      * @see     java.net.URLConnection#getHeaderField(java.lang.String)
  363.      * @since   JDK1.0
  364.      */
  365.     public String getContentType() {
  366.     return getHeaderField("content-type");
  367.     }
  368.  
  369.     /**
  370.      * Returns the value of the <code>content-encoding</code> header field.
  371.      *
  372.      * @return  the content encoding of the resource that the URL references,
  373.      *          or <code>null</code> if not known.
  374.      * @see     java.net.URLConnection#getHeaderField(java.lang.String)
  375.      * @since   JDK1.0
  376.      */
  377.     public String getContentEncoding() {
  378.     return getHeaderField("content-encoding");
  379.     }
  380.  
  381.     /**
  382.      * Returns the value of the <code>expires</code> header field. 
  383.      *
  384.      * @return  the expiration date of the resource that this URL references,
  385.      *          or 0 if not known. The value is the number of seconds since
  386.      *          January 1, 1970 GMT.
  387.      * @see     java.net.URLConnection#getHeaderField(java.lang.String)
  388.      * @since   JDK1.0
  389.      */
  390.     public long getExpiration() {
  391.     return getHeaderFieldDate("expires", 0);
  392.     }
  393.  
  394.     /**
  395.      * Returns the value of the <code>date</code> header field. 
  396.      *
  397.      * @return  the sending date of the resource that the URL references,
  398.      *          or <code>0</code> if not known. The value returned is the
  399.      *          number of seconds since January 1, 1970 GMT.
  400.      * @see     java.net.URLConnection#getHeaderField(java.lang.String)
  401.      * @since   JDK1.0
  402.      */
  403.     public long getDate() {
  404.     return getHeaderFieldDate("date", 0);
  405.     }
  406.  
  407.     /**
  408.      * Returns the value of the <code>last-modified</code> header field. 
  409.      * The result is the number of seconds since January 1, 1970 GMT.
  410.      *
  411.      * @return  the date the resource referenced by this
  412.      *          <code>URLConnection</code> was last modified, or 0 if not known.
  413.      * @see     java.net.URLConnection#getHeaderField(java.lang.String)
  414.      * @since   JDK1.0
  415.      */
  416.     public long getLastModified() {
  417.     return getHeaderFieldDate("last-modified", 0);
  418.     }
  419.  
  420.     /**
  421.      * Returns the value of the specified header field. Names of  
  422.      * header fields to pass to this method can be obtained from 
  423.      * getHeaderFieldKey.
  424.      *
  425.      * @param   name   the name of a header field. 
  426.      * @return  the value of the named header field, or <code>null</code>
  427.      *          if there is no such field in the header.
  428.      * @see     java.net.URLConnection#getHeaderFieldKey(int)
  429.      * @since   JDK1.0
  430.      */
  431.     public String getHeaderField(String name) {
  432.     return null;
  433.     }
  434.  
  435.     /**
  436.      * Returns the value of the named field parsed as a number.
  437.      * <p>
  438.      * This form of <code>getHeaderField</code> exists because some 
  439.      * connection types (e.g., <code>http-ng</code>) have pre-parsed 
  440.      * headers. Classes for that connection type can override this method 
  441.      * and short-circuit the parsing. 
  442.      *
  443.      * @param   name      the name of the header field.
  444.      * @param   Default   the default value.
  445.      * @return  the value of the named field, parsed as an integer. The
  446.      *          <code>Default</code> value is returned if the field is
  447.      *          missing or malformed.
  448.      * @since   JDK1.0
  449.      */
  450.     public int getHeaderFieldInt(String name, int Default) {
  451.     try {
  452.         return Integer.parseInt(getHeaderField(name));
  453.     } catch(Throwable t) {}
  454.     return Default;
  455.     }
  456.  
  457.     /**
  458.      * Returns the value of the named field parsed as date.
  459.      * The result is the number of seconds since January 1, 1970 GMT
  460.      * represented by the named field. 
  461.      * <p>
  462.      * This form of <code>getHeaderField</code> exists because some 
  463.      * connection types (e.g., <code>http-ng</code>) have pre-parsed 
  464.      * headers. Classes for that connection type can override this method 
  465.      * and short-circuit the parsing. 
  466.      *
  467.      * @param   name     the name of the header field.
  468.      * @param   Default   a default value.
  469.      * @return  the value of the field, parsed as a date. The value of the
  470.      *          <code>Default</code> argument is returned if the field is
  471.      *          missing or malformed.
  472.      * @since   JDK1.0
  473.      */
  474.     public long getHeaderFieldDate(String name, long Default) {
  475.     try {
  476.         return Date.parse(getHeaderField(name));
  477.     } catch(Throwable t) {}
  478.     return Default;
  479.     }
  480.  
  481.     /**
  482.      * Returns the key for the <code>n</code><sup>th</sup> header field.
  483.      *
  484.      * @param   n   an index.
  485.      * @return  the key for the <code>n</code><sup>th</sup> header field,
  486.      *          or <code>null</code> if there are fewer than <code>n</code>
  487.      *          fields.
  488.      * @since   JDK1.0
  489.      */
  490.     public String getHeaderFieldKey(int n) {
  491.     return null;
  492.     }
  493.  
  494.     /**
  495.      * Returns the value for the <code>n</code><sup>th</sup> header field. 
  496.      * It returns <code>null</code> if there are fewer than 
  497.      * <code>n</code> fields. 
  498.      * <p>
  499.      * This method can be used in conjunction with the 
  500.      * <code>getHeaderFieldKey</code> method to iterate through all 
  501.      * the headers in the message. 
  502.      *
  503.      * @param   n   an index.
  504.      * @return  the value of the <code>n</code><sup>th</sup> header field.
  505.      * @see     java.net.URLConnection#getHeaderFieldKey(int)
  506.      * @since   JDK1.0
  507.      */
  508.     public String getHeaderField(int n) {
  509.     return null;
  510.     }
  511.  
  512.     /**
  513.      * Retrieves the contents of this URL connection. 
  514.      * <p>
  515.      * This method first determines the content type of the object by 
  516.      * calling the <code>getContentType</code> method. If this is 
  517.      * the first time that the application has seen that specific content 
  518.      * type, a content handler for that content type is created: 
  519.      * <ol>
  520.      * <li>If the application has set up a content handler factory instance
  521.      *     using the <code>setContentHandlerFactory</code> method, the
  522.      *     <code>createContentHandler</code> method of that instance is called
  523.      *     with the content type as an argument; the result is a content
  524.      *     handler for that content type.
  525.      * <li>If no content handler factory has yet been set up, or if the
  526.      *     factory's <code>createContentHandler</code> method returns
  527.      *     <code>null</code>, then the application loads the class named:
  528.      *     <ul><code>
  529.      *         sun.net.www.content.<<i>contentType</i>>
  530.      *     </code></ul>
  531.      *     where <<i>contentType</i>> is formed by taking the
  532.      *     content-type string, replacing all slash characters with a
  533.      *     <code>period</code> ('.'), and all other non-alphanumeric characters
  534.      *     with the underscore character '<code>_</code>'. The alphanumeric
  535.      *     characters are specifically the 26 uppercase ASCII letters
  536.      *     '<code>A</code>' through '<code>Z</code>', the 26 lowercase ASCII
  537.      *     letters '<code>a</code>' through '<code>z</code>', and the 10 ASCII
  538.      *     digits '<code>0</code>' through '<code>9</code>'. If the specified
  539.      *     class does not exist, or is not a subclass of
  540.      *     <code>ContentHandler</code>, then an
  541.      *     <code>UnknownServiceException</code> is thrown.
  542.      * </ol>
  543.      *
  544.      * @return     the object fetched. The <code>instanceOf</code> operation
  545.      *               should be used to determine the specific kind of object
  546.      *               returned.
  547.      * @exception  IOException              if an I/O error occurs while
  548.      *               getting the content.
  549.      * @exception  UnknownServiceException  if the protocol does not support
  550.      *               the content type.
  551.      * @see        java.net.ContentHandlerFactory#createContentHandler(java.lang.String)
  552.      * @see        java.net.URLConnection#getContentType()
  553.      * @see        java.net.URLConnection#setContentHandlerFactory(java.net.ContentHandlerFactory)
  554.      * @since      JDK1.0
  555.      */
  556.     public Object getContent() throws IOException {
  557.     return getContentHandler().getContent(this);
  558.     }
  559.  
  560.     /**
  561.      * Returns an input stream that reads from this open connection.
  562.      *
  563.      * @return     an input stream that reads from this open connection.
  564.      * @exception  IOException              if an I/O error occurs while
  565.      *               creating the input stream.
  566.      * @exception  UnknownServiceException  if the protocol does not support
  567.      *               input.
  568.      * @since   JDK1.0
  569.      */
  570.     public InputStream getInputStream() throws IOException {
  571.     throw new UnknownServiceException("protocol doesn't support input");
  572.     }
  573.  
  574.     /**
  575.      * Returns an output stream that writes to this connection.
  576.      *
  577.      * @return     an output stream that writes to this connection.
  578.      * @exception  IOException              if an I/O error occurs while
  579.      *               creating the output stream.
  580.      * @exception  UnknownServiceException  if the protocol does not support
  581.      *               output.
  582.      * @since   JDK1.0
  583.      */
  584.     public OutputStream getOutputStream() throws IOException {
  585.     throw new UnknownServiceException("protocol doesn't support output");
  586.     }
  587.  
  588.     /**
  589.      * Returns a <code>String</code> representation of this URL connection.
  590.      *
  591.      * @return  a string representation of this <code>URLConnection</code>.
  592.      * @since   JDK1.0
  593.      */
  594.     public String toString() {
  595.     return this.getClass().getName() + ":" + url;
  596.     }
  597.  
  598.     /**
  599.      * Sets the value of the <code>doInput</code> field for this 
  600.      * <code>URLConnection</code> to the specified value. 
  601.      * <p>
  602.      * A URL connection can be used for input and/or output.  Set the DoInput
  603.      * flag to true if you intend to use the URL connection for input,
  604.      * false if not.  The default is true unless DoOutput is explicitly
  605.      * set to true, in which case DoInput defaults to false.
  606.      *
  607.      * @param   value   the new value.
  608.      * @see     java.net.URLConnection#doInput
  609.      * @since   JDK1.0
  610.      */
  611.     public void setDoInput(boolean doinput) {
  612.     if (connected)
  613.         throw new IllegalAccessError("Already connected");
  614.     doInput = doinput;
  615.     }
  616.  
  617.     /**
  618.      * Returns the value of this <code>URLConnection</code>'s
  619.      * <code>doInput</code> flag.
  620.      *
  621.      * @return  the value of this <code>URLConnection</code>'s
  622.      *          <code>doInput</code> flag.
  623.      * @see     java.net.URLConnection#doInput
  624.      * @since   JDK1.0
  625.      */
  626.     public boolean getDoInput() {
  627.     return doInput;
  628.     }
  629.  
  630.     /**
  631.      * Sets the value of the <code>doOutput</code> field for this 
  632.      * <code>URLConnection</code> to the specified value. 
  633.      * <p>
  634.      * A URL connection can be used for input and/or output.  Set the DoOutput
  635.      * flag to true if you intend to use the URL connection for output,
  636.      * false if not.  The default is false.
  637.      *
  638.      * @param   value   the new value.
  639.      * @see     java.net.URLConnection#doOutput
  640.      * @since   JDK1.0
  641.      */
  642.     public void setDoOutput(boolean dooutput) {
  643.     if (connected)
  644.         throw new IllegalAccessError("Already connected");
  645.     doOutput = dooutput;
  646.     }
  647.  
  648.     /**
  649.      * Returns the value of this <code>URLConnection</code>'s
  650.      * <code>doOutput</code> flag.
  651.      *
  652.      * @return  the value of this <code>URLConnection</code>'s
  653.      *          <code>doOutput</code> flag.
  654.      * @see     java.net.URLConnection#doOutput
  655.      * @since   JDK1.0
  656.      */
  657.     public boolean getDoOutput() {
  658.     return doOutput;
  659.     }
  660.  
  661.     /**
  662.      * Set the value of the <code>allowUserInteraction</code> field of 
  663.      * this <code>URLConnection</code>. 
  664.      *
  665.      * @param   allowuserinteraction   the new value.
  666.      * @see     java.net.URLConnection#allowUserInteraction
  667.      * @since   JDK1.0
  668.      */
  669.     public void setAllowUserInteraction(boolean allowuserinteraction) {
  670.     if (connected)
  671.         throw new IllegalAccessError("Already connected");
  672.     allowUserInteraction = allowuserinteraction;
  673.     }
  674.  
  675.     /**
  676.      * Returns the value of the <code>allowUserInteraction</code> field for
  677.      * this object.
  678.      *
  679.      * @return  the value of the <code>allowUserInteraction</code> field for
  680.      *          this object.
  681.      * @see     java.net.URLConnection#allowUserInteraction
  682.      * @since   JDK1.0
  683.      */
  684.     public boolean getAllowUserInteraction() {
  685.     return allowUserInteraction;
  686.     }
  687.  
  688.     /**
  689.      * Sets the default value of the 
  690.      * <code>allowUserInteraction</code> field for all future 
  691.      * <code>URLConnection</code> objects to the specified value. 
  692.      *
  693.      * @param   defaultallowuserinteraction   the new value.
  694.      * @see     java.net.URLConnection#allowUserInteraction
  695.      * @since   JDK1.0
  696.      */
  697.     public static void setDefaultAllowUserInteraction(boolean defaultallowuserinteraction) {
  698.     defaultAllowUserInteraction = defaultallowuserinteraction;
  699.     }
  700.  
  701.     /**
  702.      * Returns the default value of the <code>allowUserInteraction</code>
  703.      * field.
  704.      * <p>
  705.      * Ths default is "sticky", being a part of the static state of all
  706.      * URLConnections.  This flag applies to the next, and all following
  707.      * URLConnections that are created.
  708.      *
  709.      * @return  the default value of the <code>allowUserInteraction</code>
  710.      *          field.
  711.      * @see     java.net.URLConnection#allowUserInteraction
  712.      * @since   JDK1.0
  713.      */
  714.     public static boolean getDefaultAllowUserInteraction() {
  715.     return defaultAllowUserInteraction;
  716.     }
  717.  
  718.     /**
  719.      * Sets the value of the <code>useCaches</code> field of this 
  720.      * <code>URLConnection</code> to the specified value. 
  721.      * <p>
  722.      * Some protocols do caching of documents.  Occasionally, it is important
  723.      * to be able to "tunnel through" and ignore the caches (e.g., the
  724.      * "reload" button in a browser).  If the UseCaches flag on a connection
  725.      * is true, the connection is allowed to use whatever caches it can.
  726.      *  If false, caches are to be ignored.
  727.      *  The default value comes from DefaultUseCaches, which defaults to
  728.      * true.
  729.      *
  730.      * @see     java.net.URLConnection#useCaches
  731.      * @since   JDK1.0
  732.      */
  733.     public void setUseCaches(boolean usecaches) {
  734.     if (connected)
  735.         throw new IllegalAccessError("Already connected");
  736.     useCaches = usecaches;
  737.     }
  738.  
  739.     /**
  740.      * Returns the value of this <code>URLConnection</code>'s
  741.      * <code>useCaches</code> field.
  742.      *
  743.      * @return  the value of this <code>URLConnection</code>'s
  744.      *          <code>useCaches</code> field.
  745.      * @see     java.net.URLConnection#useCaches
  746.      * @since   JDK1.0
  747.      */
  748.     public boolean getUseCaches() {
  749.     return useCaches;
  750.     }
  751.  
  752.     /**
  753.      * Sets the value of the <code>ifModifiedSince</code> field of 
  754.      * this <code>URLConnection</code> to the specified value.
  755.      *
  756.      * @param   value   the new value.
  757.      * @see     java.net.URLConnection#ifModifiedSince
  758.      * @since   JDK1.0
  759.      */
  760.     public void setIfModifiedSince(long ifmodifiedsince) {
  761.     if (connected)
  762.         throw new IllegalAccessError("Already connected");
  763.     ifModifiedSince = ifmodifiedsince;
  764.     }
  765.  
  766.     /**
  767.      * Returns the value of this object's <code>ifModifiedSince</code> field.
  768.      *
  769.      * @return  the value of this object's <code>ifModifiedSince</code> field.
  770.      * @see     java.net.URLConnection#ifModifiedSince
  771.      * @since   JDK1.0
  772.      */
  773.     public long getIfModifiedSince() {
  774.     return ifModifiedSince;
  775.     }
  776.  
  777.    /**
  778.      * Returns the default value of a <code>URLConnection</code>'s
  779.      * <code>useCaches</code> flag.
  780.      * <p>
  781.      * Ths default is "sticky", being a part of the static state of all
  782.      * URLConnections.  This flag applies to the next, and all following
  783.      * URLConnections that are created.
  784.      *
  785.      * @return  the default value of a <code>URLConnection</code>'s
  786.      *          <code>useCaches</code> flag.
  787.      * @see     java.net.URLConnection#useCaches
  788.      * @since   JDK1.0
  789.      */
  790.     public boolean getDefaultUseCaches() {
  791.     return defaultUseCaches;
  792.     }
  793.  
  794.    /**
  795.      * Sets the default value of the <code>useCaches</code> field to the 
  796.      * specified value. 
  797.      *
  798.      * @param   defaultusecaches   the new value.
  799.      * @see     java.net.URLConnection#useCaches
  800.      * @since   JDK1.0
  801.      */
  802.     public void setDefaultUseCaches(boolean defaultusecaches) {
  803.     defaultUseCaches = defaultusecaches;
  804.     }
  805.  
  806.     /**
  807.      * Sets the general request property. 
  808.      *
  809.      * @param   key     the keyword by which the request is known
  810.      *                  (e.g., "<code>accept</code>").
  811.      * @param   value   the value associated with it.
  812.      * @since   JDK1.0
  813.      */
  814.     public void setRequestProperty(String key, String value) {
  815.     if (connected)
  816.         throw new IllegalAccessError("Already connected");
  817.     }
  818.  
  819.     /**
  820.      * Returns the value of the named general request property for this
  821.      * connection.
  822.      *
  823.      * @return  the value of the named general request property for this
  824.      *           connection.
  825.      * @since   JDK1.0
  826.      */
  827.     public String getRequestProperty(String key) {
  828.     if (connected)
  829.         throw new IllegalAccessError("Already connected");
  830.     return null;
  831.     }
  832.  
  833.     /**
  834.      * Sets the default value of a general request property. When a 
  835.      * <code>URLConnection</code> is created, it is initialized with 
  836.      * these properties. 
  837.      *
  838.      * @param   key     the keyword by which the request is known
  839.      *                  (e.g., "<code>accept</code>").
  840.      * @param   value   the value associated with the key.
  841.      * @since   JDK1.0
  842.      */
  843.     public static void setDefaultRequestProperty(String key, String value) {
  844.     }
  845.  
  846.     /**
  847.      * Returns the value of the default request property. Default request 
  848.      * properties are set for every connection. 
  849.      *
  850.      * @return  the value of the default request property for the specified key.
  851.      * @see     java.net.URLConnection#setDefaultRequestProperty(java.lang.String, java.lang.String)
  852.      * @since   JDK1.0
  853.      */
  854.     public static String getDefaultRequestProperty(String key) {
  855.     return null;
  856.     }
  857.  
  858.     /**
  859.      * The ContentHandler factory.
  860.      */
  861.     static ContentHandlerFactory factory;
  862.  
  863.     /**
  864.      * Sets the <code>ContentHandlerFactory</code> of an 
  865.      * application. It can be called at most once by an application. 
  866.      * <p>
  867.      * The <code>ContentHandlerFactory</code> instance is used to 
  868.      * construct a content handler from a content type 
  869.      *
  870.      * @param      fac   the desired factory.
  871.      * @exception  Error  if the factory has already been defined.
  872.      * @see        java.net.ContentHandlerFactory
  873.      * @see        java.net.URLConnection#getContent()
  874.      * @since      JDK1.0
  875.      */
  876.     public static synchronized void setContentHandlerFactory(ContentHandlerFactory fac) {
  877.     if (factory != null) {
  878.         throw new Error("factory already defined");
  879.     }
  880.     SecurityManager security = System.getSecurityManager();
  881.     if (security != null) {
  882.         security.checkSetFactory();
  883.     }
  884.     factory = fac;
  885.     }
  886.  
  887.     private static Hashtable handlers = new Hashtable();
  888.     private static ContentHandler UnknownContentHandlerP = new UnknownContentHandler();
  889.  
  890.     /**
  891.      * Gets the Content Handler appropriate for this connection.
  892.      * @param connection the connection to use.
  893.      */
  894.     synchronized ContentHandler getContentHandler()
  895.     throws UnknownServiceException
  896.     {
  897.     String contentType = getContentType();
  898.     ContentHandler handler = null;
  899.     if (contentType == null)
  900.         throw new UnknownServiceException("no content-type");
  901.     try {
  902.         handler = (ContentHandler) handlers.get(contentType);
  903.         if (handler != null)
  904.         return handler;
  905.     } catch(Exception e) {
  906.     }
  907.     if (factory != null)
  908.         handler = factory.createContentHandler(contentType);
  909.     if (handler == null) {
  910.         try {
  911.         handler = lookupContentHandlerClassFor(contentType);
  912.         } catch(Exception e) {
  913.         e.printStackTrace();
  914.         handler = UnknownContentHandlerP;
  915.         }
  916.         handlers.put(contentType, handler);
  917.     }
  918.     return handler;
  919.     }
  920.  
  921.     private static final String contentClassPrefix = "sun.net.www.content";
  922.     private static final String contentPathProp = "java.content.handler.pkgs";
  923.  
  924.     /**
  925.      * Looks for a content handler in a user-defineable set of places.
  926.      * By default it looks in sun.net.www.content, but users can define a 
  927.      * vertical-bar delimited set of class prefixes to search through in 
  928.      * addition by defining the java.content.handler.pkgs property.
  929.      * The class name must be of the form:
  930.      * <pre>
  931.      *     {package-prefix}.{major}.{minor}
  932.      * e.g.
  933.      *     YoyoDyne.experimental.text.plain
  934.      * </pre>
  935.      */
  936.     private ContentHandler lookupContentHandlerClassFor(String contentType)
  937.     throws InstantiationException, IllegalAccessException, ClassNotFoundException {
  938.     String contentHandlerClassName = typeToPackageName(contentType);
  939.  
  940.     String contentHandlerPkgPrefixes = getContentHandlerPkgPrefixes();
  941.  
  942.     StringTokenizer packagePrefixIter =
  943.         new StringTokenizer(contentHandlerPkgPrefixes, "|");
  944.     
  945.     while (packagePrefixIter.hasMoreTokens()) {
  946.         String packagePrefix = packagePrefixIter.nextToken().trim();
  947.  
  948.         try {
  949.         String name = packagePrefix + "." + contentHandlerClassName;
  950.         ContentHandler handler =
  951.             (ContentHandler) Class.forName(name).newInstance();
  952.         return handler;
  953.         } catch(Exception e) {
  954.         }
  955.     }
  956.     
  957.     return UnknownContentHandlerP;
  958.     }
  959.  
  960.     /**
  961.      * Utility function to map a MIME content type into an equivalent
  962.      * pair of class name components.  For example: "text/html" would
  963.      * be returned as "text.html"
  964.      */
  965.     private String typeToPackageName(String contentType) {
  966.     int len = contentType.length();
  967.     char nm[] = new char[len];
  968.     contentType.getChars(0, len, nm, 0);
  969.     for (int i = 0; i < len; i++) {
  970.         char c = nm[i];
  971.         if (c == '/') {
  972.         nm[i] = '.';
  973.         } else if (!('A' <= c && c <= 'Z' ||
  974.                'a' <= c && c <= 'z' ||
  975.                '0' <= c && c <= '9')) {
  976.         nm[i] = '_';
  977.         }
  978.     }
  979.     return new String(nm);
  980.     }
  981.  
  982.  
  983.     /**
  984.      * Returns a vertical bar separated list of package prefixes for potential
  985.      * content handlers.  Tries to get the java.content.handler.pkgs property
  986.      * to use as a set of package prefixes to search.  Whether or not
  987.      * that property has been defined, the sun.net.www.content is always
  988.      * the last one on the returned package list.
  989.      */
  990.     private String getContentHandlerPkgPrefixes() {
  991.     String packagePrefixList = System.getProperty(contentPathProp, "");
  992.     if (packagePrefixList != "") {
  993.         packagePrefixList += "|";
  994.     }
  995.     
  996.     return packagePrefixList + contentClassPrefix;
  997.     }
  998.  
  999.     /**
  1000.      * Tries to determine the content type of an object, based 
  1001.      * on the specified "file" component of a URL.
  1002.      * This is a convenience method that can be used by 
  1003.      * subclasses that override the <code>getContentType</code> method. 
  1004.      *
  1005.      * @param   fname   a filename.
  1006.      * @return  a guess as to what the content type of the object is,
  1007.      *          based upon its file name.
  1008.      * @see     java.net.URLConnection#getContentType()
  1009.      * @since   JDK1.0
  1010.      */
  1011.     protected static String guessContentTypeFromName(String fname) {
  1012.     String contentType = null;
  1013.     if (fileNameMap != null) {
  1014.         contentType = fileNameMap.getContentTypeFor(fname);
  1015.     }
  1016.  
  1017.     return contentType;
  1018.     }
  1019.  
  1020.     /**
  1021.      * Tries to determine the type of an input stream based on the 
  1022.      * characters at the beginning of the input stream. This method can 
  1023.      * be used by subclasses that override the 
  1024.      * <code>getContentType</code> method. 
  1025.      * <p>
  1026.      * Ideally, this routine would not be needed. But many 
  1027.      * <code>http</code> servers return the incorrect content type; in 
  1028.      * addition, there are many nonstandard extensions. Direct inspection 
  1029.      * of the bytes to determine the content type is often more accurate 
  1030.      * than believing the content type claimed by the <code>http</code> server.
  1031.      *
  1032.      * @param      is   an input stream that supports marks.
  1033.      * @return     a guess at the content type, or <code>null</code> if none
  1034.      *             can be determined.
  1035.      * @exception  IOException  if an I/O error occurs while reading the
  1036.      *               input stream.
  1037.      * @see        java.io.InputStream#mark(int)
  1038.      * @see        java.io.InputStream#markSupported()
  1039.      * @see        java.net.URLConnection#getContentType()
  1040.      * @since      JDK1.0
  1041.      */
  1042.     static public String guessContentTypeFromStream(InputStream is) throws IOException
  1043.     {
  1044.     is.mark(10);
  1045.     int c1 = is.read();
  1046.     int c2 = is.read();
  1047.     int c3 = is.read();
  1048.     int c4 = is.read();
  1049.     int c5 = is.read();
  1050.     int c6 = is.read();
  1051.     is.reset();
  1052.     if (c1 == 0xCA && c2 == 0xFE && c3 == 0xBA && c4 == 0xBE)
  1053.         return "application/java-vm";
  1054.     if (c1 == 0xAC && c2 == 0xED)
  1055.         // next two bytes are version number, currently 0x00 0x05
  1056.         return "application/x-java-serialized-object";
  1057.     if (c1 == 'G' && c2 == 'I' && c3 == 'F' && c4 == '8')
  1058.         return "image/gif";
  1059.     if (c1 == '#' && c2 == 'd' && c3 == 'e' && c4 == 'f')
  1060.         return "image/x-bitmap";
  1061.     if (c1 == '!' && c2 == ' ' && c3 == 'X' && c4 == 'P' && c5 == 'M' && c6 == '2')
  1062.         return "image/x-pixmap";
  1063.     if (c1 == '<')
  1064.         if (c2 == '!'
  1065.             || (c6 == '>'
  1066.             && (c2 == 'h' && (c3 == 't' && c4 == 'm' && c5 == 'l' ||
  1067.                       c3 == 'e' && c4 == 'a' && c5 == 'd')
  1068.               || c2 == 'b' && c3 == 'o' && c4 == 'd' && c5 == 'y')))
  1069.         return "text/html";
  1070.  
  1071.     if (c1 == 0x2E && c2 == 0x73 && c3 == 0x6E && c4 == 0x64)
  1072.         return "audio/basic";  // .au format, big endian
  1073.     if (c1 == 0x64 && c2 == 0x6E && c3 == 0x73 && c4 == 0x2E)
  1074.         return "audio/basic";  // .au format, little endian
  1075.     if (c1 == '<')
  1076.         if (c2 == '!'
  1077.         || ((c2 == 'h' && (c3 == 't' && c4 == 'm' && c5 == 'l' ||
  1078.                    c3 == 'e' && c4 == 'a' && c5 == 'd')
  1079.              || c2 == 'b' && c3 == 'o' && c4 == 'd' && c5 == 'y'))
  1080.         || ((c2 == 'H' && (c3 == 'T' && c4 == 'M' && c5 == 'L' ||
  1081.                    c3 == 'E' && c4 == 'A' && c5 == 'D')
  1082.              || c2 == 'B' && c3 == 'O' && c4 == 'D' && c5 == 'Y')))
  1083.         return "text/html";
  1084.  
  1085.     if (c1 == 0xFF && c2 == 0xD8 && c3 == 0xFF && c4 == 0xE0)
  1086.         return "image/jpeg";
  1087.     if (c1 == 0xFF && c2 == 0xD8 && c3 == 0xFF && c4 == 0xEE)
  1088.         return "image/jpg";
  1089.  
  1090.     if (c1 == 'R' && c2 == 'I' && c3 == 'F' && c4 == 'F')
  1091.         /* I don't know if this is official but evidence
  1092.          * suggests that .wav files start with "RIFF" - brown
  1093.          */
  1094.         return "audio/x-wav";  
  1095.     return null;
  1096.     }
  1097. }
  1098.  
  1099. class UnknownContentHandler extends ContentHandler {
  1100.     public Object getContent(URLConnection uc) throws IOException {
  1101.     return uc.getInputStream();
  1102.     }
  1103. }
  1104.